home *** CD-ROM | disk | FTP | other *** search
- /* RelationshipKeySetter.m created by cfeder on Tue 08-Nov-1994 */
-
- #import "RelationshipKeySetter.h"
- #import "ValueForKey.h"
- #import <objc/objc-runtime.h>
-
- @implementation EOEntity (attrsNamed)
- - attributesNamed:(NSArray *)names
- {
- int i, count = [names count];
- NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];
- for(i=0; i<count; i++) {
- EOAttribute *attr = [self attributeNamed:[names objectAtIndex:i]];
- if (attr)
- [result addObject:attr];
- }
- return result;
- }
-
- - createObject
- {
- id eo = nil;
- const char *className = [self className];
- Class eoClass = objc_lookUpClass (className);
-
- if (!eoClass) eoClass = [EOGenericRecord class];
-
- if (eoClass) {
- eo = [eoClass allocWithZone:[self zone]];
- if ([eo respondsToSelector:@selector(initWithPrimaryKey:entity:)])
- eo = [eo initWithPrimaryKey:nil entity:self];
- else
- [eo init];
- }
- return [eo autorelease];
- }
- @end
-
-
- @implementation EORelationship (setPropsInDestObject)
- - (NSArray *)sourceKeys
- {
- EORelationship *sourceRelationship = [self isFlattened]
- ? [[self componentRelationships] objectAtIndex:0] : self;
- NSArray *joins = [sourceRelationship joins];
- int i, count = [joins count];
- NSMutableArray *results = [NSMutableArray arrayWithCapacity:count];
-
- for (i = 0; i < count; i++) {
- EOJoin *join = [joins objectAtIndex:i];
- [results addObject:[[join sourceAttribute] name]];
- }
- return results;
- }
-
- - (void)setJoinPropertiesInDestinationObject:destination fromSourceObject:source
- {
- NSArray *joins = [self joins];
- int i, count = [joins count];
-
- for (i = 0; i < count; i++) {
- EOJoin *join = [joins objectAtIndex:i];
- id val = [(NSObject *)source valueForKey:[[join sourceAttribute] name]];
- if (!val) val = [EONull null];
- [destination takeValue:val forKey:[[join destinationAttribute] name]];
- }
- }
-
- - (void)setJoinPropertiesInSourceObject:source fromDestinationObject:destination
- {
-
- NSArray *joins = [self joins];
- int i, count = [joins count];
-
- for (i = 0; i < count; i++) {
- EOJoin *join = [joins objectAtIndex:i];
- id val = [(NSObject*)destination valueForKey:[[join destinationAttribute] name]];
- if (!val) val = [EONull null];
- [source takeValue:val forKey:[[join sourceAttribute] name]];
- }
- }
-
- - (NSDictionary *)destinationValuesFromSourceObject:sourceObject
- {
- NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
- [self setJoinPropertiesInDestinationObject:dictionary fromSourceObject:sourceObject];
- return dictionary;
- }
-
- - (BOOL)hasJoinsOnPrimaryKeyOfSourceEntity
- {
- // FIX ME!
- // this is not quite right for multi-attribute keys (the ordering may
- // cause a false mismatch)
- return [[self sourceKeys] isEqual:[[self entity] primaryKeyAttributeNames]];
- }
-
- - (void)updateMasterObject:master withNewDestinationObject:destination
- // For to-one relationships!
- {
- // Decide which way to propagate the attributes based on which side of the
- // relationship hooks to a primary key.
- if ([self hasJoinsOnPrimaryKeyOfSourceEntity])
- [self setJoinPropertiesInDestinationObject:destination fromSourceObject:master];
- else
- [self setJoinPropertiesInSourceObject:destination fromDestinationObject:master];
- }
-
- - linkObjectForSourceObject:master destinationObject:destination
- // created an intermediate object for many-to-many relationship through
- // an intermediate table. Initializes keys of intermediate object using
- // keys from source and destination object
- {
- NSArray *relationships = [self componentRelationships];
- EORelationship *sourceToLink = [relationships objectAtIndex:0];
- EORelationship *linkToDestination = [relationships objectAtIndex:1];
- EOEntity *linkEntity = [sourceToLink destinationEntity];
- id link = [linkEntity createObject];
- [sourceToLink setJoinPropertiesInDestinationObject:link fromSourceObject:master];
- [linkToDestination setJoinPropertiesInSourceObject:link fromDestinationObject:destination];
- return link;
- }
-
- - updateKeysForSourceObject:source destinationObject:destination
- // Sets keys on source or destination to maintain consistency for
- // the source to now map to destination for this relationship.
- // Does not actually assign destination to ivar in source (just messes
- // with the keys).
- // Returns the modified object (source or destination). In the case of
- // a many to many returns a newly created link object.
- // The caller is reposible for inserting or updating the returned
- // object in the database.
- {
- id modifiedObject = nil;
-
- if ([self isToMany]) {
- // figure out what values we need to snarf from our parents
- if ([self isFlattened]) {
- // Many to many create link obj Delete link none to-many
- // I'm assuming there's only one link object...
- modifiedObject = [self linkObjectForSourceObject:source destinationObject:destination];
- } else {
- // PK -> FK D->FK := M->PK none none to-many
- [self setJoinPropertiesInDestinationObject:destination fromSourceObject:source];
- modifiedObject = destination;
- }
- } else {
- if ([self hasJoinsOnPrimaryKeyOfSourceEntity]) {
- // PK -> PK D->PK := M->PK None none to-one
- [self setJoinPropertiesInDestinationObject:destination fromSourceObject:source];
- modifiedObject = destination;
- } else {
- // FK -> PK M->FK := D->PK M->FK=NULL none to-one
- // We need to update the master with a new foreign key.
- // send it to the dataSource as well...
- [self setJoinPropertiesInSourceObject:source fromDestinationObject:destination];
- modifiedObject = source;
- }
- }
- return modifiedObject;
- }
-
-
- - updateKeysForDeleteOfDestinationObject:destination fromSourceObject:source
- // Sets keys on source or destination to maintain consistency for
- // a delete of the destination from the source. Returns the object
- // modified, or a synthesized link object that must be deleted to
- // affect the delete. The caller is responsible for updating the
- // source object, or deleting the destination or link in the database.
- //
- // This does not actually update destination to ivar in source (just messes
- // with the keys).
- {
- id modifiedObject = nil;
-
- if ([self isToMany]) {
- // figure out what values we need to snarf from our parents
- if ([self isFlattened]) {
- // Many to many create link obj Delete link to-many
- // I'm assuming there's only one link object...
- modifiedObject = [self linkObjectForSourceObject:source destinationObject:destination];
- } else {
- // PK -> FK D->FK := M->PK Delete D to-many
- // Nil out foreign key in destination
- [self setJoinPropertiesInDestinationObject:destination fromSourceObject:nil];
- modifiedObject = destination;
- }
- } else {
- if ([self hasJoinsOnPrimaryKeyOfSourceEntity]) {
- // PK -> PK D->PK := M->PK delete D to-one
- // no use nilling out destinations primary key. Row must be deleted
- modifiedObject = destination;
- } else {
- // FK -> PK M->FK := D->PK M->FK=NULL to-one
- // nil out foreign key in source
- [self setJoinPropertiesInSourceObject:source fromDestinationObject:nil];
- modifiedObject = source;
- }
- }
- return modifiedObject;
- }
-
- @end
-
-
-